<?php

namespace yak\layui\widgets\grid;

use yak\layui\search\LayuiSearchInterface;
use Yii;
use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\base\Widget;
use yii\data\ActiveDataProvider;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;

/**
 * Class LayuiGridView
 * @package yak\layui\widgets\tables
 */
class LayuiGridView extends Widget
{
    /**
     * @var Model | LayuiSearchInterface
     */
    public $searchModel;

    /**
     * @var ActiveDataProvider
     */
    public $dataProvider;

    /**
     * @var array
     */
    protected $columns = [];

    /**
     * @var array
     */
    public $tableOptions = [];

    /**
     * @var array
     */
    public $editorOptions = [];

    /**
     * @var array
     */
    public $eventOptions = [];

    /**
     * @var array
     */
    public $events = [];

    /**
     * @var
     */
    public $tableId;

    /**
     * @var
     */
    public $tableFilter;

    /**
     * @var
     */
    public $searchFilter;

    /**
     * @var bool
     */
    public $cacheCount = true;

    /**
     * @var string
     */
    public $scripts = '';

    /**
     * @var string
     */
    public $sort = 'client';

    public function init()
    {
        $this->columns = $this->searchModel->columns();
        $this->initColumns();

        parent::init(); // TODO: Change the autogenerated stub
    }

    protected function renderTable()
    {
        $default = [
            'id' => $this->tableId,
            'elem' => '#' . $this->tableId,
            'limit' => $this->searchModel->pageSize(),
            'limits' => $this->searchModel->limits(),
            'cols' => [
                $this->renderCols()
            ],
            'method' => 'post',
            'request' => [
                'pageName' => 'page',
                'limitName' => 'per-page'
            ]
        ];

        return ArrayHelper::merge($default, $this->tableOptions);
    }

    protected function renderEditor()
    {
        $default = [
            'method' => 'post'
        ];
        return ArrayHelper::merge($default, $this->editorOptions);
    }

    public function run()
    {
        $config = [
            '_csrf' => Yii::$app->request->csrfToken,
            'searchModelName' => $this->searchModel->formName(),
            'searchModelClass' => get_class($this->searchModel),
            'modelClass' => get_parent_class($this->searchModel),
            'searchFilter' => $this->searchFilter,
            'tableId' => $this->tableId,
            'tableFilter' => $this->tableFilter,
            'sort' => $this->sort,
            'countCache' => $this->cacheCount,
            'table' => $this->renderTable(),
            'editor' => $this->renderEditor(),
            'eventOptions' => $this->eventOptions
        ];

        $json = Json::encode($config);
        $events = Json::encode($this->events);
        $this->view->registerJs("layui.use('grid', function(){var pager = layui.grid; {$this->scripts}; pager.render({$json}, {$events})})", \yii\web\View::POS_END);
    }


    protected function initColumns()
    {
        if (empty($this->columns)) {
            $this->guessColumns();
        }
        foreach ($this->columns as $i => $column) {
            if (is_string($column)) {
                $column = $this->createDataColumn($column);
            } else {
                $column = Yii::createObject(array_merge([
                    'class' => DataColumn::className(),
                    'grid' => $this,
                ], $column));
            }
            if (!$column->visible) {
                unset($this->columns[$i]);
                continue;
            }
            $this->columns[$i] = $column;
        }
    }

    /**
     * This function tries to guess the columns to show from the given data
     * if [[columns]] are not explicitly specified.
     */
    protected function guessColumns()
    {
        $models = $this->dataProvider->getModels();
        $model = reset($models);
        if (is_array($model) || is_object($model)) {
            foreach ($model as $name => $value) {
                if ($value === null || is_scalar($value) || is_callable([$value, '__toString'])) {
                    $this->columns[] = (string)$name;
                }
            }
        }
    }

    /**
     * @param $text
     * @return object|DataColumn
     * @throws InvalidConfigException
     */
    protected function createDataColumn($text)
    {
        if (!preg_match('/^([^:]+)(:(\w*))?(:(.*))?$/', $text, $matches)) {
            throw new InvalidConfigException('The column must be specified in the format of "attribute", "attribute:format" or "attribute:format:label"');
        }

        return Yii::createObject([
            'class' => DataColumn::className(),
            'grid' => $this,
            'attribute' => $matches[1],
            'format' => isset($matches[3]) ? $matches[3] : 'text',
            'label' => isset($matches[5]) ? $matches[5] : null,
        ]);
    }

    protected function renderCols()
    {
        return array_map(function (LayuiColInterface $column) {
            return $column->generateCol();
        }, $this->columns);
    }
}